#!/usr/bin/env ts-node

/**
 * Performance testing example of @roasmax/rabbitmq
 */

import {
  RabbitMQClient,
  createPerformanceTester,
  createLogger,
} from '../src';

async function performanceExample(): Promise<void> {
  console.log('🚀 RabbitMQ Performance Testing');
  console.log('================================');

  // Create client with optimized configuration for performance
  const client = RabbitMQClient.create({
    host: process.env.RABBITMQ_HOST || 'localhost',
    port: parseInt(process.env.RABBITMQ_PORT || '5672'),
    username: process.env.RABBITMQ_USERNAME || 'guest',
    password: process.env.RABBITMQ_PASSWORD || 'guest',
    heartbeat: 60,
    connectionTimeout: 5000,
  });

  try {
    await client.initialize();
    console.log('✅ Performance client initialized');

    // Get connection pool for performance testing
    const connectionPool = (client as any).connectionPool;
    const logger = createLogger('PerformanceTest');
    
    // Create performance tester
    const tester = createPerformanceTester(connectionPool, logger);

    console.log('\n📊 Running Performance Test Suite');
    console.log('==================================');

    // Run comprehensive test suite
    const results = await tester.runTestSuite('perf_test');

    // Display results
    console.log('\n📈 Performance Test Results');
    console.log('===========================');

    console.log('\n🚄 Throughput Test:');
    console.log(`  Messages: ${results.throughput.messageCount.toLocaleString()}`);
    console.log(`  Duration: ${results.throughput.duration.toLocaleString()}ms`);
    console.log(`  Throughput: ${results.throughput.throughput.toFixed(2)} messages/second`);
    console.log(`  Concurrent Producers: ${results.throughput.concurrentProducers}`);

    console.log('\n⚡ Latency Test:');
    console.log(`  Samples: ${results.latency.messageCount.toLocaleString()}`);
    if (results.latency.latencyStats) {
      console.log(`  Min Latency: ${results.latency.latencyStats.min}ms`);
      console.log(`  Max Latency: ${results.latency.latencyStats.max}ms`);
      console.log(`  Avg Latency: ${results.latency.latencyStats.avg.toFixed(2)}ms`);
      console.log(`  P95 Latency: ${results.latency.latencyStats.p95}ms`);
      console.log(`  P99 Latency: ${results.latency.latencyStats.p99}ms`);
    }

    console.log('\n🔄 End-to-End Test:');
    console.log(`  Messages: ${results.endToEnd.messageCount.toLocaleString()}`);
    console.log(`  Duration: ${results.endToEnd.duration.toLocaleString()}ms`);
    console.log(`  Throughput: ${results.endToEnd.throughput.toFixed(2)} messages/second`);
    if (results.endToEnd.latencyStats) {
      console.log(`  Avg E2E Latency: ${results.endToEnd.latencyStats.avg.toFixed(2)}ms`);
      console.log(`  P95 E2E Latency: ${results.endToEnd.latencyStats.p95}ms`);
      console.log(`  P99 E2E Latency: ${results.endToEnd.latencyStats.p99}ms`);
    }

    // Run individual tests with different parameters
    console.log('\n🔬 Detailed Performance Analysis');
    console.log('================================');

    // Test different message sizes
    console.log('\n📏 Message Size Impact:');
    const messageSizes = [100, 1024, 10240, 102400]; // 100B, 1KB, 10KB, 100KB
    
    for (const size of messageSizes) {
      console.log(`\n  Testing ${size} byte messages:`);
      
      const throughputResult = await tester.runThroughputTest(
        `perf_size_${size}`,
        1000,
        5,
        size
      );
      
      console.log(`    Throughput: ${throughputResult.throughput.toFixed(2)} msg/s`);
      console.log(`    Duration: ${throughputResult.duration}ms`);
      
      // Clean up
      await new Promise(resolve => setTimeout(resolve, 1000));
    }

    // Test different concurrency levels
    console.log('\n👥 Concurrency Impact:');
    const concurrencyLevels = [1, 5, 10, 20];
    
    for (const concurrency of concurrencyLevels) {
      console.log(`\n  Testing ${concurrency} concurrent producers:`);
      
      const throughputResult = await tester.runThroughputTest(
        `perf_conc_${concurrency}`,
        5000,
        concurrency,
        1024
      );
      
      console.log(`    Throughput: ${throughputResult.throughput.toFixed(2)} msg/s`);
      console.log(`    Messages per producer: ${(5000 / concurrency).toFixed(0)}`);
      
      // Clean up
      await new Promise(resolve => setTimeout(resolve, 1000));
    }

    // Performance recommendations
    console.log('\n💡 Performance Recommendations');
    console.log('==============================');

    const avgThroughput = results.throughput.throughput;
    const avgLatency = results.latency.latencyStats?.avg || 0;
    const e2eLatency = results.endToEnd.latencyStats?.avg || 0;

    if (avgThroughput < 1000) {
      console.log('⚠️  Low throughput detected. Consider:');
      console.log('   - Increasing connection pool size');
      console.log('   - Using more concurrent producers');
      console.log('   - Optimizing message serialization');
    } else if (avgThroughput > 10000) {
      console.log('🎉 Excellent throughput! Your setup is well optimized.');
    } else {
      console.log('✅ Good throughput. Room for optimization if needed.');
    }

    if (avgLatency > 100) {
      console.log('⚠️  High latency detected. Consider:');
      console.log('   - Reducing message size');
      console.log('   - Optimizing network configuration');
      console.log('   - Using local RabbitMQ instance');
    } else {
      console.log('✅ Good latency performance.');
    }

    if (e2eLatency > avgLatency * 3) {
      console.log('⚠️  High end-to-end latency. Consider:');
      console.log('   - Optimizing message processing logic');
      console.log('   - Increasing consumer concurrency');
      console.log('   - Using batch processing for high volume');
    } else {
      console.log('✅ Good end-to-end performance.');
    }

    // Connection stats
    console.log('\n🔗 Connection Statistics');
    console.log('========================');
    const connectionStats = client.getConnectionStats();
    console.log(`Total Connections: ${connectionStats.totalConnections}`);
    console.log(`Available Connections: ${connectionStats.availableConnections}`);
    console.log(`Busy Connections: ${connectionStats.busyConnections}`);
    console.log(`Pool Size: ${connectionStats.poolSize}`);

    console.log('\n✅ Performance testing completed!');

  } catch (error) {
    console.error('❌ Performance test error:', error);
  } finally {
    // Clean up
    await client.close();
    console.log('🔒 Performance client closed');
  }
}

// Run the example
if (require.main === module) {
  performanceExample().catch(console.error);
}

export { performanceExample };
